package com.wpp.start;

import com.wpp.annotation.RpcService;
import com.wpp.coder.RpcDecoder;
import com.wpp.constant.Constant;
import com.wpp.handler.UserServiceHandler;
import com.wpp.protocol.RpcRequest;
import com.wpp.register.ZkRegisterCenter;
import com.wpp.serializer.JSONSerializer;
import com.wpp.util.SpringContentHolder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.UnknownHostException;


/**
 * @author by wpp25
 * @Classname Bootstarp
 * @Description
 * @Date 2020/11/26 20:55
 */
@Component
public class RpcServerBootStrap implements InitializingBean, ApplicationContextAware {

    private ApplicationContext applicationContext;
    private  int port;
    private String ip;
    private String SERVER = Constant.SERVER_NAME_FIRST;


    @Resource
    private ZkRegisterCenter registerCenter;


    /**
     *  服务器启动程序
     */
    public void startServer() throws InterruptedException {
        System.out.println("server started...");
        UserServiceHandler userServiceHandler = new UserServiceHandler(applicationContext,port);

        NioEventLoopGroup boosGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();

        // 服务器端启动引导对象
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        // 对 启动引导对象进行配置
        try {
            serverBootstrap.group(boosGroup,workGroup)
                    // 设置通道为nio
                    .channel(NioServerSocketChannel.class)
                    // 创建监听channel
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            // 获取管道对象
                            ChannelPipeline pipeline = nioSocketChannel.pipeline();
                            // 给管道对象piplie 设置编码
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new RpcDecoder(RpcRequest.class,new JSONSerializer()));
                            // 把我们自定义的handler添加到通道中
                            pipeline.addLast(userServiceHandler);

                        }
                    });
            ChannelFuture future = serverBootstrap.bind(ip, port).sync();
            future.addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    if (future.isSuccess()) {
                        // 启动成功
                        registerService();
                    }
                }
            });
            //  等待服务端 监听端口关闭
            ChannelFuture closeFuture = future.channel().closeFuture().sync();
            closeFuture.addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    System.out.println("服务器 下线了。。。");
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("启动服务失败了。。。");
        } finally {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }


    @Override
    public void afterPropertiesSet() throws Exception {
        this.port = Constant.PORT_SERVER_SECOND;
        this.ip = "127.0.0.1";
        startServer();

    }

    public void registerService() throws UnknownHostException {

        // 从容器中获取 被@RpcService注解 注册的服务
        String[] beanNamesForAnnotation = applicationContext.getBeanNamesForAnnotation(RpcService.class);
        for (String beanName : beanNamesForAnnotation) {
            Object bean = applicationContext.getBean(beanName);
            RpcService annotation = bean.getClass().getAnnotation(RpcService.class);
            Class<?> aClass = annotation.serviceClass();

            registerCenter.register(aClass.getName(),new StringBuilder(ip).append(":").append(port).toString());
        }

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
